package com.caishi.lkx.user.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.caishi.lkx.common.role.Role;
import com.caishi.lkx.user.dto.LoginDto;
import com.caishi.lkx.user.ienum.type.UserAccountType;
import com.caishi.lkx.user.ienum.type.UserType;
import com.caishi.lkx.user.mapper.AdminUserMapper;
import com.caishi.lkx.user.model.AdminUserModel;
import com.caishi.lkx.user.model.IUserModel;
import com.caishi.lkx.user.model.LoginInfoModel;
import com.caishi.lkx.user.model.UserModel;
import com.caishi.lkx.user.service.*;
import com.zzw.common.threadpool.SysThreadPool;
import com.zzw.common.entity.IBaseMapper;
import com.zzw.common.exception.BizException;
import com.zzw.common.exception.BizRuntimeException;

import com.caishi.lkx.user.login.LoginServiceComposite;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

/**
 * @author by keray
 * date:2021/4/13 5:02 下午
 */
@Service("adminUserService")
//@DubboService(interfaceClass = IRpcAdminUserService.class)
public class AdminUserServiceImpl implements IAdminUserService {

    @Resource
    private AdminUserMapper adminUserMapper;

    @Resource
    private IUserService<UserModel> userService;

    @Resource
    private LoginServiceComposite loginServiceComposite;
    @Resource
    private IActionRoleService actionRoleService;

    @Resource
    private IPositionService positionService;

    @Resource
    private ILoginInfoService loginInfoService;
    @Resource
    private IDistributionUserService distributionUserService;

    @Override
    public IBaseMapper<AdminUserModel, String> getMapper() {
        return adminUserMapper;
    }

    @Override
    public IUserService<UserModel> baseService() {
        return userService;
    }

    @Override
    public AdminUserModel register(LoginDto loginDto, HttpServletRequest request, HttpServletResponse response) throws BizException {
        throw new BizException();
    }

    @Override
    public AdminUserModel register(AdminUserModel userModel) {
        if (userModel.getUserType() == 0) {
            userModel.addUserType(UserType.admin);
        }
        UserModel baseModel = userService.register(userModel.toUserModel());
        userModel.userInfoCopy(baseModel);
        return registerCheck(baseModel, userModel);
    }

    private AdminUserModel registerCheck(UserModel baseUser, AdminUserModel model) {
        if (adminUserMapper.contains(baseUser.getId())) {
            this.simpleUpdate(model.clearUserModelMessage());
            return model;
        }
        model = model.clearUserModelMessage();
        model.setId(baseUser.getId());
        return this.insert(model).userInfoCopy(baseUser);
    }


    @Override
    public AdminUserModel adminUserDetail(String userId) {
        AdminUserModel model = getUserDetail(userId);
        if (StrUtil.isNotBlank(model.getParentId())) {
            model.setParent(getUserDetail(model.getParentId()));
        }
        model.setPositions(positionService.userHavePosition(model.getId()));
        if(Role.distributer.name().equals(model.getApiRoleName())){
            // 分销等级
            model.setDistributionLevel(distributionUserService.getById(model.getId()).getLevelsId());
        }

        return model;
    }

    @Override
    public IPage<AdminUserModel> search(Map<String, Object> param, Page<AdminUserModel> page, boolean total) {
        Future<Long> future = CompletableFuture.supplyAsync(() -> null);
        if (total) {
            future = SysThreadPool.submit(() -> adminUserMapper.searchUserCount(param));
        }
        List<AdminUserModel> adminUserModels = adminUserMapper.searchUser(page.offset(), page.getSize(), param,
                page.getOrders().stream().filter(OrderItem::isAsc).map(OrderItem::getColumn).collect(Collectors.toList()),
                page.getOrders().stream().filter(o -> !o.isAsc()).map(OrderItem::getColumn).collect(Collectors.toList())
        );
        try {
            Long count = future.get();
            return page.setRecords(adminUserModels).setTotal(count == null ? page.getRecords().size() : count);
        } catch (InterruptedException | ExecutionException e) {
            throw new BizRuntimeException(e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AdminUserModel addUser(AdminUserModel model, List<String> roleIds, List<Long> positionIds, String username, String password, UserAccountType loginType) throws BizException {
        Assert.isTrue(model.getUserType() != null && model.getUserType() != 0);
        Assert.notEmpty(model.getMobile(), "手机号不能为空");
        IUserModel userModel = loginServiceComposite.register(
                LoginInfoModel.builder()
                        .account(username)
                        .loginType(loginType)
                        .certificate(password)
                        .build(),
                model
        );
        if (CollUtil.isNotEmpty(roleIds)) {
            model.setApiRoleName(String.join(",", roleIds));
            actionRoleService.userSettingRolesByIds(model.getId(), roleIds);
        }
        if (CollUtil.isNotEmpty(positionIds)) {
            positionService.userSettingPositionByIds(userModel.getId(), positionIds);
        }
        return model;
    }

    @Override
    public AdminUserModel builder() {
        return new AdminUserModel();
    }

//    @Override
//    public Map<String, Object> rpcPages(Map<String, Object> param, long total, long current, long size, boolean btotal) {
//        Page<AdminUserModel> p = new Page<>();
//        p.setCurrent(current);
//        p.setTotal(total);
//        p.setSize(size);
//        var list = this.search(param, p, btotal);
//        List<AdminUserModel> records = list.getRecords();
//        var rpcList = records.stream().map(v -> BeanUtil.copyProperties(v, RpcAdminUserModel.class)).collect(Collectors.toList());
//        Map<String, Object> map = new HashMap<>();
//        map.put("current", list.getCurrent());
//        map.put("total", list.getTotal());
//        map.put("size", list.getSize());
//        map.put("list", rpcList);
//        return map;
//    }
//
//    @Override
//    @Transactional(rollbackFor = Exception.class)
//    public RpcAdminUserModel rpcRegister(RpcAdminUserModel userModel) {
//        var model = BeanUtil.copyProperties(userModel, AdminUserModel.class);
//        var rpcModel = this.register(model);
//        return BeanUtil.copyProperties(rpcModel, RpcAdminUserModel.class);
//    }
//
//    @Override
//    public RpcAdminUserModel rpcGetUserDetail(String id) {
//        var model = getUserDetail(id);
//        return BeanUtil.copyProperties(model, RpcAdminUserModel.class);
//    }
//
//    @Override
//    public RpcAdminUserModel rpcUpdate(RpcAdminUserModel userModel) {
//        var model = BeanUtil.copyProperties(userModel, AdminUserModel.class);
//        return BeanUtil.copyProperties(update(model), RpcAdminUserModel.class);
//    }
//
//    @Override
//    public List<RpcAdminUserModel> rpcGetListByIds(List<String> ids) {
//        var list = adminUserMapper.searchUserByIds(ids);
//        return list.stream().map(v -> BeanUtil.copyProperties(v, RpcAdminUserModel.class)).collect(Collectors.toList());
//    }
}
